﻿using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Reflection;

namespace Library.Common.Common
{
    /// <summary>
    /// 枚举操作的扩展方法
    /// </summary>
    public static class EnumExtentions
    {
        /// <summary>
        /// 扩展方法：获取枚举项描述信息
        /// <para>
        ///     如果没有获取到描述信息（没有找到DescriptionAttribute特性），则返回该枚举项的字符串
        /// </para>
        /// </summary>
        /// <param name="enumItem">需要获取的枚举项</param>
        /// <returns>该枚举项的描述信息</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="Exception"></exception>
        public static string GetDescription(this Enum enumItem)
        {
            try
            {
                if (null == enumItem) {
                    throw new ArgumentNullException("enumItem");
                }
                Type type = enumItem.GetType();

                // 获取枚举公共成员
                var enumMembersInfo = type.GetMember(enumItem.ToString());
                if (enumMembersInfo != null && enumMembersInfo.Length > 0)
                {
                    // 获取自定义特性
                    object[] attrs = enumMembersInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                    if (attrs != null && attrs.Length > 0)
                        return ((DescriptionAttribute)attrs[0]).Description;
                }
                return enumItem.ToString();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>  
        /// 扩展方法：根据枚举值得到相应的枚举定义字符串  
        /// </summary>  
        /// <param name="value">枚举值</param>  
        /// <param name="enumType">枚举类型</param>  
        /// <returns>枚举的项字符串</returns>  
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="Exception"></exception>
        public static string GetEnumStringByValue(this int value, Type enumType)
        {
            try
            {
                if (null == enumType) {
                    throw new ArgumentNullException("enumType");
                };
                NameValueCollection keyValuePairs = GetEnumKeyValuePairsByEnumType(enumType);
                return keyValuePairs[value.ToString()];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>  
        /// 根据枚举类型获得该枚举类型的字符串键值对集合
        /// </summary>  
        /// <param name="enumType">枚举类型</param>  
        /// <returns>该枚举类型的字符串键值对集合</returns>  
        private static NameValueCollection GetEnumKeyValuePairsByEnumType(Type enumType)
        {
            NameValueCollection keyValuePairs = new NameValueCollection();

            // 获取枚举类型的所有公共字段
            FieldInfo[] fields = enumType.GetFields();

            string strValue = string.Empty;

            foreach (FieldInfo field in fields)
            {
                if (field.FieldType.IsEnum)
                {
                    // 获取枚举值的字符串
                    strValue = ((int)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null)).ToString();
                    keyValuePairs.Add(strValue, field.Name);
                }
            }
            return keyValuePairs;
        }

        /// <summary>  
        /// 扩展方法：根据枚举值得到对应枚举项的自定义性Description特性中的描述
        /// <para>
        ///     如果没有定义此属性则返回空串
        /// </para>
        /// </summary>  
        /// <param name="value">枚举的值</param>  
        /// <param name="enumType">枚举类型</param>  
        /// <returns>指定枚举项的描述内容</returns>  
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="Exception"></exception>
        public static string GetEnumDescriptionByValue(this int value, Type enumType)
        {
            try
            {
                if (null == enumType) {
                    throw new ArgumentNullException("enumType");
                }
                NameValueCollection keyValuePairs = GetNVCFromEnumValue(enumType);
                return keyValuePairs[value.ToString()];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>  
        /// 根据枚举类型得到其所有的 值 与 枚举定义Description属性 的集合  
        /// </summary>  
        /// <param name="enumType"></param>  
        /// <returns>处理结果</returns>  
        private static NameValueCollection GetNVCFromEnumValue(Type enumType)
        {
            NameValueCollection keyValuePairs = new NameValueCollection();

            Type typeDescription = typeof(DescriptionAttribute);

            FieldInfo[] fields = enumType.GetFields();

            // 枚举描述的字符串
            string enumDescriptionString = string.Empty;

            // 枚举值的字符串
            string enumValueString = string.Empty;

            foreach (FieldInfo field in fields)
            {
                if (field.FieldType.IsEnum)
                {
                    enumValueString = ((int)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null)).ToString();

                    // 获取字段的自定义特性
                    object[] fieldCustomAttributes = field.GetCustomAttributes(typeDescription, true);

                    if (fieldCustomAttributes.Length > 0)
                    {
                        DescriptionAttribute description = (DescriptionAttribute)fieldCustomAttributes[0];
                        enumDescriptionString = description.Description;
                    }
                    else
                    {
                        enumDescriptionString = "";
                    }
                    keyValuePairs.Add(enumValueString, enumDescriptionString);
                }
            }
            return keyValuePairs;
        }
    }
}
